home *** CD-ROM | disk | FTP | other *** search
/ LiquidLibrary 2005 September / LiquidLibrary 2005 Sep - Disc 1.iso / pc / Portfolio Browser / Filters / PDF / LIB / gs_lev2.ps < prev    next >
Text File  |  2003-01-03  |  29KB  |  855 lines

  1. %    Copyright (C) 1990, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This software is licensed to a single customer by Artifex Software Inc.
  3. % under the terms of a specific OEM agreement.
  4.  
  5. % $RCSfile$ $Revision$
  6. % Initialization file for Level 2 functions.
  7. % When this is run, systemdict is still writable,
  8. % but (almost) everything defined here goes into level2dict.
  9.  
  10. level2dict begin
  11.  
  12. % ------ System and user parameters ------ %
  13.  
  14. % User parameters must obey save/restore, and must also be maintained
  15. % per-context.  We implement the former, and some of the latter, here
  16. % with PostScript code.  NOTE: our implementation assumes that user
  17. % parameters change only as a result of setuserparams -- that there are
  18. % no user parameters that are ever changed dynamically by the interpreter
  19. % (although the interpreter may adjust the value presented to setuserparams)
  20. %
  21. % There are two types of user parameters: those which are actually
  22. % maintained in the interpreter, and those which exist only at the
  23. % PostScript level.  We maintain the current state of both types in
  24. % a read-only local dictionary named userparams, defined in systemdict.
  25. % In a multi-context system, each context has its own copy of this
  26. % dictionary.  In addition, there is a constant dictionary named
  27. % psuserparams where each key is the name of a user parameter that exists
  28. % only in PostScript and the value is a procedure to check that the value
  29. % is legal: setuserparams uses this for checking the values.
  30. % setuserparams updates userparams explicitly, in addition to setting
  31. % any user parameters in the interpreter; thus we can use userparams
  32. % to reset those parameters after a restore or a context switch.
  33. % NOTE: the name userparams is known to the interpreter, and in fact
  34. % the interpreter creates the userparams dictionary.
  35.  
  36. % Check parameters that are managed at the PostScript level.
  37. /.checkparamtype {        % <newvalue> <type> .checkparamtype <bool>
  38.   exch type eq
  39. } .bind def
  40. /.checksetparams {        % <newdict> <opname> <checkdict>
  41.                 %   .checksetparams <newdict>
  42.   2 index {
  43.         % Stack: newdict opname checkdict key newvalue
  44.     3 copy 3 1 roll .knownget {
  45.       exec not {
  46.     pop pop pop load /typecheck signalerror
  47.       } if
  48.       dup type /stringtype eq {
  49.     dup rcheck not {
  50.       pop pop pop load /invalidaccess signalerror
  51.     } if
  52.       } if
  53.     } {
  54.       pop
  55.     } ifelse pop pop
  56.   } forall pop pop
  57. } .bind def    % not odef, shouldn't reset stacks
  58.  
  59. % currentuser/systemparams creates and returns a dictionary in the
  60. % current VM.  The easiest way to make this work is to copy any composite
  61. % PostScript-level parameters to global VM.  Currently, the only such
  62. % parameters are strings.  In fact, we always copy string parameters,
  63. % so that we can be sure the contents won't be changed.
  64. /.copyparam {            % <value> .copyparam <value'>
  65.   dup type /stringtype eq {
  66.     .currentglobal true .setglobal
  67.     1 index length string exch .setglobal
  68.     copy readonly
  69.   } if
  70. } .bind def
  71.  
  72. % Some user parameters are managed entirely at the PostScript level.
  73. % We take care of that here.
  74. systemdict begin
  75. /psuserparams 40 dict def
  76. /getuserparam {            % <name> getuserparam <value>
  77.   /userparams .systemvar 1 index get exch pop
  78. } odef
  79. % Fill in userparams (created by the interpreter) with current values.
  80. mark .currentuserparams
  81. counttomark 2 idiv {
  82.   userparams 3 1 roll put
  83. } repeat pop
  84. /.definepsuserparam {        % <name> <value> .definepsuserparam -
  85.   psuserparams 3 copy pop
  86.   type cvlit /.checkparamtype cvx 2 packedarray cvx put
  87.   userparams 3 1 roll put
  88. } .bind def
  89. end
  90. /currentuserparams {        % - currentuserparams <dict>
  91.   /userparams .systemvar dup length dict .copydict
  92. } odef
  93. /setuserparams {        % <dict> setuserparams -
  94.     % Check that we will be able to set the PostScript-level
  95.     % user parameters.
  96.   /setuserparams /psuserparams .systemvar .checksetparams
  97.     % Set the C-level user params.  If this succeeds, we know that
  98.     % the password check succeeded.
  99.   dup .setuserparams
  100.     % Now set the PostScript-level params.
  101.     % The interpreter may have adjusted the values of some of the
  102.     % parameters, so we have to read them back.
  103.   dup {
  104.     /userparams .systemvar 2 index known {
  105.       psuserparams 2 index known not {
  106.     pop dup .getuserparam
  107.       } if
  108.       .copyparam
  109.       /userparams .systemvar 3 1 roll .forceput  % userparams is read-only
  110.     } {
  111.       pop pop
  112.     } ifelse
  113.   } forall
  114.     % A context switch might have occurred during the above loop,
  115.     % causing the interpreter-level parameters to be reset.
  116.     % Set them again to the new values.  From here on, we are safe,
  117.     % since a context switch will consult userparams.
  118.   .setuserparams
  119. } .bind odef
  120. % Initialize user parameters managed here.
  121. /JobName () .definepsuserparam
  122.  
  123. % Restore must restore the user parameters.
  124. % (Since userparams is in local VM, save takes care of saving them.)
  125. /restore {        % <save> restore -
  126.   //restore /userparams .systemvar .setuserparams
  127. } .bind odef
  128.  
  129. % The pssystemparams dictionary holds some system parameters that
  130. % are managed entirely at the PostScript level.
  131. systemdict begin
  132. currentdict /pssystemparams known not {
  133.   /pssystemparams 40 dict readonly def
  134. } if
  135. /getsystemparam {        % <name> getsystemparam <value>
  136.   //pssystemparams 1 index .knownget { exch pop } { .getsystemparam } ifelse
  137. } odef
  138. end
  139. /currentsystemparams {        % - currentsystemparams <dict>
  140.   mark .currentsystemparams //pssystemparams { } forall .dicttomark
  141. } odef
  142. /setsystemparams {        % <dict> setsystemparams -
  143.     % Check that we will be able to set the PostScript-level
  144.     % system parameters.
  145.    /setsystemparams //pssystemparams mark exch {
  146.      type cvlit /.checkparamtype cvx 2 packedarray cvx
  147.    } forall .dicttomark .checksetparams
  148.     % Set the C-level system params.  If this succeeds, we know that
  149.     % the password check succeeded.
  150.    dup .setsystemparams
  151.     % Now set the PostScript-level params.  We must copy local strings
  152.     % into global VM.
  153.    dup
  154.     { //pssystemparams 2 index known
  155.        {        % Stack: key newvalue
  156.      .copyparam
  157.      //pssystemparams 3 1 roll .forceput    % pssystemparams is read-only
  158.        }
  159.        { pop pop
  160.        }
  161.       ifelse
  162.     }
  163.    forall pop
  164. } .bind odef
  165.  
  166. % Initialize the passwords.
  167. % NOTE: the names StartJobPassword and SystemParamsPassword are known to
  168. % the interpreter, and must be bound to noaccess strings.
  169. % The length of these strings must be max_password (iutil2.h) + 1.
  170. /StartJobPassword 65 string noaccess def
  171. /SystemParamsPassword 65 string noaccess def
  172.  
  173. % Redefine cache parameter setting to interact properly with userparams.
  174. /setcachelimit {
  175.   mark /MaxFontItem 2 index .dicttomark setuserparams pop
  176. } .bind odef
  177. /setcacheparams {
  178.     % The MaxFontCache parameter is a system parameter, which we might
  179.     % not be able to set.  Fortunately, this doesn't matter, because
  180.     % system parameters don't have to be synchronized between this code
  181.     % and the VM.
  182.   counttomark 1 add copy setcacheparams
  183.   currentcacheparams    % mark size lower upper
  184.     3 -1 roll pop
  185.     /MinFontCompress 3 1 roll
  186.     /MaxFontItem exch
  187.   .dicttomark setuserparams
  188.   cleartomark
  189. } .bind odef
  190.  
  191. % Add bogus user and system parameters to satisfy badly written PostScript
  192. % programs that incorrectly assume the existence of all the parameters
  193. % listed in Appendix C of the Red Book.  Note that some of these may become
  194. % real parameters later: code near the end of gs_init.ps takes care of
  195. % removing any such parameters from ps{user,system}params.
  196.  
  197. % psuserparams
  198.   /MaxFormItem 100000 .definepsuserparam
  199.   /MaxPatternItem 20000 .definepsuserparam
  200.   /MaxScreenItem 48000 .definepsuserparam
  201.   /MaxUPathItem 5000 .definepsuserparam
  202.  
  203. pssystemparams begin
  204.   /CurDisplayList 0 .forcedef
  205.   /CurFormCache 0 .forcedef
  206.   /CurOutlineCache 0 .forcedef
  207.   /CurPatternCache 0 .forcedef
  208.   /CurUPathCache 0 .forcedef
  209.   /CurScreenStorage 0 .forcedef
  210.   /CurSourceList 0 .forcedef
  211.   /DoPrintErrors false .forcedef
  212.   /MaxDisplayList 140000 .forcedef
  213.   /MaxFormCache 100000 .forcedef
  214.   /MaxOutlineCache 65000 .forcedef
  215.   /MaxPatternCache 100000 .forcedef
  216.   /MaxUPathCache 300000 .forcedef
  217.   /MaxScreenStorage 84000 .forcedef
  218.   /MaxSourceList 25000 .forcedef
  219.   /RamSize 4194304 .forcedef
  220. end
  221.  
  222. % Define the procedures for handling comment scanning.  The names
  223. % %ProcessComment and %ProcessDSCComment are known to the interpreter.
  224. % These procedures take the file and comment string and file as operands.
  225. /.checkprocesscomment {
  226.   dup null eq {
  227.     pop true
  228.   } {
  229.     dup xcheck {
  230.       type dup /arraytype eq exch /packedarraytype eq or
  231.     } {
  232.       pop false
  233.     } ifelse
  234.   } ifelse
  235. } .bind def
  236. /ProcessComment null .definepsuserparam
  237. psuserparams /ProcessComment {.checkprocesscomment} put
  238. (%ProcessComment) cvn {
  239.   /ProcessComment getuserparam
  240.   dup null eq { pop pop pop } { exec } ifelse
  241. } bind def
  242. /ProcessDSCComment null .definepsuserparam
  243. psuserparams /ProcessDSCComment {.checkprocesscomment} put
  244. (%ProcessDSCComment) cvn {
  245.   /ProcessDSCComment getuserparam
  246.   dup null eq { pop pop pop } { exec } ifelse
  247. } bind def
  248.  
  249. % ------ Miscellaneous ------ %
  250.  
  251. (<<) cvn            % - << -mark-
  252.   /mark load def
  253. (>>) cvn            % -mark- <key1> <value1> ... >> <dict>
  254.   /.dicttomark load def
  255. /languagelevel 2 def
  256. % When running in Level 2 mode, this interpreter is supposed to be
  257. % compatible with Adobe version 2017.
  258. /version (2017) readonly def
  259.  
  260. % If binary tokens are supported by this interpreter,
  261. % set an appropriate default binary object format.
  262. /setobjectformat where
  263.  { pop
  264.    /RealFormat getsystemparam (IEEE) eq { 1 } { 3 } ifelse
  265.    /ByteOrder getsystemparam { 1 add } if
  266.    setobjectformat
  267.  } if
  268.  
  269. % Aldus Freehand versions 2.x check for the presence of the
  270. % setcolor operator, and if it is missing, substitute a procedure.
  271. % Unfortunately, the procedure takes different parameters from
  272. % the operator.  As a result, files produced by this application
  273. % cause an error if the setcolor operator is actually defined
  274. % and 'bind' is ever used.  Aldus fixed this bug in Freehand 3.0,
  275. % but there are a lot of files created by the older versions
  276. % still floating around.  Therefore, at Adobe's suggestion,
  277. % we implement the following dreadful hack in the 'where' operator:
  278. %      If the key is /setcolor, and
  279. %        there is a dictionary named FreeHandDict, and
  280. %        currentdict is that dictionary,
  281. %      then "where" consults only that dictionary and not any other
  282. %        dictionaries on the dictionary stack.
  283. .wheredict /setcolor {
  284.   /FreeHandDict .where {
  285.     /FreeHandDict get currentdict eq {
  286.       pop currentdict /setcolor known { currentdict true } { false } ifelse
  287.     } {
  288.       .where
  289.     } ifelse
  290.   } {
  291.     .where
  292.   } ifelse
  293. } bind put
  294.  
  295. % ------ Virtual memory ------ %
  296.  
  297. /currentglobal            % - currentglobal <bool>
  298.   /currentshared load def
  299. /gcheck                % <obj> gcheck <bool>
  300.   /scheck load def
  301. /setglobal            % <bool> setglobal -
  302.   /setshared load def
  303. % We can make the global dictionaries very small, because they auto-expand.
  304. /globaldict currentdict /shareddict .knownget not { 4 dict } if def
  305. /GlobalFontDirectory SharedFontDirectory def
  306.  
  307. % VMReclaim and VMThreshold are user parameters.
  308. /setvmthreshold {        % <int> setvmthreshold -
  309.   mark /VMThreshold 2 index .dicttomark setuserparams pop
  310. } odef
  311. /vmreclaim {            % <int> vmreclaim -
  312.   dup 0 gt {
  313.     .vmreclaim
  314.   } {
  315.     mark /VMReclaim 2 index .dicttomark setuserparams pop
  316.   } ifelse
  317. } odef
  318. -1 setvmthreshold
  319.  
  320. % ------ IODevices ------ %
  321.  
  322. /.getdevparams where {
  323.   pop /currentdevparams {    % <iodevice> currentdevparams <dict>
  324.     .getdevparams .dicttomark
  325.   } odef
  326. } if
  327. /.putdevparams where {
  328.   pop /setdevparams {        % <iodevice> <dict> setdevparams -
  329.     mark 1 index { } forall counttomark 2 add index
  330.     .putdevparams pop pop
  331.   } odef
  332. } if
  333.  
  334. % ------ Job control ------ %
  335.  
  336. serverdict begin
  337.  
  338. % We could protect the job information better, but we aren't attempting
  339. % (currently) to protect ourselves against maliciousness.
  340.  
  341. /.jobsave null def        % top-level save object
  342. /.jobsavelevel 0 def        % save depth of job (0 if .jobsave is null,
  343.                 % 1 otherwise)
  344. /.adminjob true def        % status of current unencapsulated job
  345.  
  346. end        % serverdict
  347.  
  348. % Because there may be objects on the e-stack created since the job save,
  349. % we have to clear the e-stack before doing the end-of-job restore.
  350. % We do this by executing a 2 .stop, which is caught by the 2 .stopped
  351. % in .runexec; we leave on the o-stack a procedure to execute aftewards.
  352. %
  353. %**************** The definition of startjob is not complete yet, since
  354. % it doesn't reset stdin/stdout.
  355. /.startnewjob {            % <exit_bool> <password_level>
  356.                 %   .startnewjob -
  357.     serverdict /.jobsave get dup null eq { pop } { restore } ifelse
  358.     exch {
  359.             % Unencapsulated job
  360.       serverdict /.jobsave null put
  361.       serverdict /.jobsavelevel 0 put
  362.       serverdict /.adminjob 3 -1 roll 1 gt put
  363.         % The Adobe documentation doesn't say what happens to the
  364.         % graphics state stack in this case, but an experiment
  365.         % produced results suggesting that a grestoreall occurs.
  366.       grestoreall
  367.     } {
  368.             % Encapsulated job
  369.       pop
  370.       serverdict /.jobsave save put
  371.       serverdict /.jobsavelevel 1 put
  372.     } ifelse
  373.         % Reset the interpreter state.
  374.   clear cleardictstack
  375.   initgraphics
  376.   false setglobal
  377. } bind def
  378. /.startjob {            % <exit_bool> <password> <finish_proc>
  379.                 %   .startjob <ok_bool>
  380.   vmstatus pop pop serverdict /.jobsavelevel get eq
  381.   2 index .checkpassword 0 gt and {
  382.     exch .checkpassword exch count 3 roll count 3 sub { pop } repeat
  383.     cleardictstack
  384.         % Reset the e-stack back to the 2 .stopped in .runexec,
  385.         % passing the finish_proc to be executed afterwards.
  386.     2 .stop
  387.   } {        % Password check failed
  388.     pop pop pop false
  389.   } ifelse
  390. } odef
  391. /startjob {            % <exit_bool> <password> startjob <ok_bool>
  392.     % This is a hack.  We really need some way to indicate explicitly
  393.     % to the interpreter that we are under control of a job server.
  394.   .userdict /quit /stop load put
  395.   { .startnewjob true } .startjob
  396. } odef
  397.  
  398. systemdict begin
  399. /quit {                % - quit -
  400.   //systemdict begin serverdict /.jobsave get null eq
  401.    { end //quit }
  402.    { /quit load /invalidaccess /signalerror load end exec }
  403.   ifelse
  404. } bind odef
  405. end
  406.  
  407. % We would like to define exitserver as a procedure, using the code
  408. % that the Red Book says is equivalent to it.  However, since startjob
  409. % resets the exec stack, we can't do this, because control would never
  410. % proceed past the call on startjob if the exitserver is successful.
  411. % Instead, we need to construct exitserver out of pieces of startjob.
  412.  
  413. serverdict begin
  414.  
  415. /exitserver {            % <password> exitserver -
  416.   true exch { .startnewjob } .startjob not {
  417.     /exitserver /invalidaccess signalerror
  418.   } if
  419. } bind def
  420.  
  421. end        % serverdict
  422.  
  423. % ------ Compatibility ------ %
  424.  
  425. % In Level 2 mode, the following replace the definitions that gs_statd.ps
  426. % installs in statusdict and serverdict.
  427. % Note that statusdict must be allocated in local VM.
  428. % We don't bother with many of these yet.
  429.  
  430. /.dict1 { exch mark 3 1 roll .dicttomark } bind def
  431.  
  432. currentglobal false setglobal 25 dict exch setglobal begin
  433. currentsystemparams
  434.  
  435. % The following do not depend on the presence of setpagedevice.
  436. /buildtime 1 index /BuildTime get def
  437. /byteorder 1 index /ByteOrder get def
  438. /checkpassword { .checkpassword 0 gt } bind def
  439. dup /DoStartPage known
  440.  { /dostartpage { /DoStartPage getsystemparam } bind def
  441.    /setdostartpage { /DoStartPage .dict1 setsystemparams } bind def
  442.  } if
  443. dup /StartupMode known
  444.  { /dosysstart { /StartupMode getsystemparam 0 ne } bind def
  445.    /setdosysstart { { 1 } { 0 } ifelse /StartupMode .dict1 setsystemparams } bind def
  446.  } if
  447. %****** Setting jobname is supposed to set userparams.JobName, too.
  448. /jobname { /JobName getuserparam } bind def
  449. /jobtimeout { /JobTimeout getuserparam } bind def
  450. /ramsize { /RamSize getsystemparam } bind def
  451. /realformat 1 index /RealFormat get def
  452. dup /PrinterName known
  453.  { /setprintername { /PrinterName .dict1 setsystemparams } bind def
  454.  } if
  455. /printername
  456.  { currentsystemparams /PrinterName .knownget not { () } if exch copy
  457.  } bind def
  458. currentuserparams /WaitTimeout known
  459.  { /waittimeout { /WaitTimeout getuserparam } bind def
  460.  } if
  461.  
  462. % The following do require setpagedevice.
  463. /.setpagedevice where { pop } { (%END PAGEDEVICE) .skipeof } ifelse
  464. /defaulttimeouts
  465.  { currentsystemparams dup
  466.    /JobTimeout .knownget not { 0 } if
  467.    exch /WaitTimeout .knownget not { 0 } if
  468.    currentpagedevice /ManualFeedTimeout .knownget not { 0 } if
  469.  } bind def
  470. /margins
  471.  { currentpagedevice /Margins .knownget { exch } { [0 0] } ifelse
  472.  } bind def
  473. /pagemargin
  474.  { currentpagedevice /PageOffset .knownget { 0 get } { 0 } ifelse
  475.  } bind def
  476. /pageparams
  477.  { currentpagedevice
  478.    dup /Orientation .knownget { 1 and ORIENT1 { 1 xor } if } { 0 } ifelse exch
  479.    dup /PageSize get aload pop 3 index 0 ne { exch } if 3 2 roll
  480.    /PageOffset .knownget { 0 get } { 0 } ifelse 4 -1 roll
  481.  } bind def
  482. /setdefaulttimeouts
  483.  { exch mark /ManualFeedTimeout 3 -1 roll
  484.    /Policies mark /ManualFeedTimeout 1 .dicttomark
  485.    .dicttomark setpagedevice
  486.    /WaitTimeout exch mark /JobTimeout 5 2 roll .dicttomark setsystemparams
  487.  } bind def
  488. /.setpagesize { 2 array astore /PageSize .dict1 setpagedevice } bind def
  489. /setduplexmode { /Duplex .dict1 setpagedevice } bind def
  490. /setmargins
  491.  { exch 2 array astore /Margins .dict1 setpagedevice
  492.  } bind def
  493. /setpagemargin { 0 2 array astore /PageOffset .dict1 setpagedevice } bind def
  494. /setpageparams
  495.  { mark /PageSize 6 -2 roll
  496.    4 index 1 and ORIENT1 { 1 } { 0 } ifelse ne { exch } if 2 array astore
  497.    /Orientation 5 -1 roll ORIENT1 { 1 xor } if
  498.    /PageOffset counttomark 2 add -1 roll 0 2 array astore
  499.    .dicttomark setpagedevice
  500.  } bind def
  501. /setresolution
  502.  { dup 2 array astore /HWResolution .dict1 setpagedevice
  503.  } bind def
  504. %END PAGEDEVICE
  505.  
  506. % The following are not implemented yet.
  507. %manualfeed
  508. %manualfeedtimeout
  509. %pagecount
  510. %pagestackorder
  511. %setpagestackorder
  512.  
  513. pop        % currentsystemparams
  514.  
  515. % Flag the current dictionary so it will be swapped when we
  516. % change language levels.  (See zmisc2.c for more information.)
  517. /statusdict currentdict def
  518.  
  519. currentdict end
  520. /statusdict exch .forcedef    % statusdict is local, systemdict is global
  521.  
  522. % The following compatibility operators are in systemdict.  They are
  523. % defined here, rather than in gs_init.ps, because they require the
  524. % resource machinery.
  525.  
  526. /devforall {        % <pattern> <proc> <scratch> devforall -
  527.   exch {
  528.     1 index currentdevparams
  529.     /Type .knownget { /FileSystem eq } { false } ifelse
  530.     { exec } { pop pop } ifelse
  531.   } /exec load 3 packedarray cvx exch
  532.   (*) 3 1 roll ppstack flush /IODevice resourceforall
  533. } odef
  534. /devstatus {        % <(%disk*%)> devstatus <searchable> <writable>
  535.             %   <hasNames> <mounted> <removable> <searchOrder>
  536.             %   <freePages> <size> true
  537.             % <string> devstatus false
  538.   dup length 5 ge {
  539.     dup 0 5 getinterval (%disk) eq {
  540.       dup /IODevice resourcestatus {
  541.     pop pop dup currentdevparams
  542.     dup /Searchable get
  543.     exch dup /Writable get
  544.     exch dup /HasNames get
  545.     exch dup /Mounted get
  546.     exch dup /Removable get
  547.     exch dup /SearchOrder get
  548.     exch dup /Free get
  549.     exch /LogicalSize get
  550.     9 -1 roll pop true
  551.       } {
  552.     pop false
  553.       } ifelse
  554.     } {
  555.       pop false
  556.     } ifelse
  557.   } {
  558.     pop false
  559.   } ifelse
  560. } odef
  561.  
  562. % ------ Color spaces ------ %
  563.  
  564. % Attempt to convert a tint transformation procedure to a Function.
  565. % The current color space defines the number of output values.
  566. /.converttinttransform {    % [.. .. .. proc ] <m>
  567.                 %   .converttinttransform [.. .. .. proc']
  568.   .currentglobal 2 index gcheck .setglobal
  569.   4 dict
  570.     dup /FunctionType 4 put
  571.     dup /Function 5 index 3 get put
  572.         % Stack: orig m global func
  573.     dup /Domain [ 6 -1 roll {0 1} repeat ] put
  574.     dup /Range [
  575.       mark currentcolor counttomark
  576.       dup 2 add 1 roll cleartomark    % # of components in alternate space
  577.     {0 1} repeat ] put
  578.   { .buildfunction } .internalstopped {
  579.     pop .setglobal
  580.   } {
  581.         % Stack: orig global func
  582.     2 index 4 array copy dup 3 4 -1 roll put
  583.     exch .setglobal exch pop
  584.   } ifelse
  585. } bind def
  586.  
  587. % Define the setcolorspace procedures:
  588. %    <colorspace> proc <colorspace'|null>
  589. % We have to define the dictionary first, so it can be bound into the
  590. % implementation procedure, but we can't populate it until the procedure
  591. % has been defined, so that the procedure can get bound into recursive calls.
  592. /colorspacedict 20 dict def
  593.  
  594. /.devcs [
  595.   /DeviceGray /DeviceRGB /DeviceCMYK /DevicePixel
  596. ] readonly def
  597. /currentcolorspace {        % - currentcolorspace <array>
  598.   .currentcolorspace dup type /integertype eq {
  599.     //.devcs exch 1 getinterval
  600.   } if
  601. } odef
  602. currentdict /.devcs .undef
  603.  
  604. /setcolorspace {        % <name|array> setcolorspace -
  605.   dup dup dup type /nametype ne { 0 get } if
  606.   //colorspacedict exch get exec
  607.   dup null eq { pop } { .setcolorspace } ifelse pop
  608. } odef
  609.  
  610. colorspacedict
  611.   dup /DeviceGray { pop 0 setgray null } bind put
  612.   dup /DeviceRGB { pop 0 0 0 setrgbcolor null } bind put
  613.   /setcmykcolor where
  614.    { pop dup /DeviceCMYK { pop 0 0 0 1 setcmykcolor null } bind put
  615.    } if
  616.   /.setcieaspace where
  617.    { pop dup /CIEBasedA { NOCIE { pop 0 setgray null } { dup 1 get .setcieaspace } ifelse } bind put
  618.    } if
  619.   /.setcieabcspace where
  620.    { pop dup /CIEBasedABC { NOCIE { pop 0 0 0 setrgbcolor null } { dup 1 get .setcieabcspace } ifelse } bind put
  621.    } if
  622.   /.setciedefspace where
  623.    { pop dup /CIEBasedDEF { NOCIE { pop 0 0 0 setrgbcolor null } { dup 1 get .setciedefspace } ifelse } bind put
  624.    } if
  625.   /.setciedefgspace where
  626.    { pop dup /CIEBasedDEFG { NOCIE { pop 0 0 0 1 setcmykcolor null } { dup 1 get .setciedefgspace } ifelse } bind put
  627.    } if
  628.   /.setseparationspace where
  629.    { pop dup /Separation { dup 2 get setcolorspace dup 1 .converttinttransform .setseparationspace } bind put
  630.    } if
  631.   /.setindexedspace where
  632.    { pop dup /Indexed { dup 1 get setcolorspace dup .setindexedspace } bind put
  633.    } if
  634.   /.nullpatternspace [/Pattern] readonly def
  635.   /.setpatternspace where
  636.    { pop dup /Pattern
  637.       { dup type /nametype eq { pop //.nullpatternspace } if
  638.     dup length 1 gt { dup 1 get setcolorspace } if
  639.         dup .setpatternspace
  640.       } bind put
  641.    } if
  642.     % If DeviceN space is included, gs_ll3.ps registers it.
  643.   /.setdevicepixelspace where
  644.    { pop dup /DevicePixel { dup .setdevicepixelspace } bind put
  645.    } if
  646.   currentdict /.nullpatternspace .undef
  647. pop
  648.  
  649. % ------ CIE color rendering ------ %
  650.  
  651. % Define findcolorrendering and a default ColorRendering ProcSet.
  652.  
  653. /findcolorrendering {        % <intentname> findcolorrendering
  654.                 %   <crdname> <found>
  655.   /ColorRendering /ProcSet findresource
  656.   1 index .namestring (.) concatstrings
  657.   1 index /GetPageDeviceName get exec .namestring (.) concatstrings
  658.   2 index /GetHalftoneName get exec .namestring
  659.   concatstrings concatstrings
  660.   dup /ColorRendering resourcestatus {
  661.     pop pop exch pop exch pop true
  662.   } {
  663.     pop /GetSubstituteCRD get exec false
  664.   } ifelse
  665. } odef
  666.  
  667. 5 dict dup begin
  668.  
  669. /GetPageDeviceName {        % - GetPageDeviceName <name>
  670.   currentpagedevice dup /PageDeviceName .knownget {
  671.     exch pop dup null eq { pop /none } if
  672.   } {
  673.     pop /none
  674.   } ifelse
  675. } bind def
  676.  
  677. /GetHalftoneName {        % - GetHalftoneName <name>
  678.   currenthalftone /HalftoneName .knownget not { /none } if
  679. } bind def
  680.  
  681. /GetSubstituteCRD {        % <intentname> GetSubstituteCRD <crdname>
  682.   pop /DefaultColorRendering
  683. } bind def
  684.  
  685. end
  686. % The resource machinery hasn't been activated, so just save the ProcSet
  687. % and let .fixresources finish the installation process.
  688. /ColorRendering exch def
  689.  
  690. % Define setcolorrendering.
  691.  
  692. /.colorrenderingtypes 5 dict def
  693.  
  694. /setcolorrendering {        % <crd> setcolorrendering -
  695.   dup /ColorRenderingType get //.colorrenderingtypes exch get exec
  696. } odef
  697.  
  698. /.setcolorrendering1 where { pop } { (%END CRD) .skipeof } ifelse
  699.  
  700. .colorrenderingtypes 1 {
  701.   dup .buildcolorrendering1 .setcolorrendering1
  702. } .bind put
  703.  
  704. % Note: the value 101 in the next line must be the same as the value of
  705. % GX_DEVICE_CRD1_TYPE in gscrdp.h.
  706. .colorrenderingtypes 101 {
  707.   dup .builddevicecolorrendering1 .setdevicecolorrendering1
  708. } .bind put
  709.  
  710. % Initialize the default CIE rendering dictionary.
  711. % The most common CIE files seem to assume the "calibrated RGB color space"
  712. % described on p. 189 of the PostScript Language Reference Manual,
  713. % 2nd Edition; we simply invert this transformation back to RGB.
  714. mark
  715.    /ColorRenderingType 1
  716. % We must make RangePQR and RangeLMN large enough so that values computed by
  717. % the assumed encoding MatrixLMN don't get clamped.
  718.    /RangePQR [0 0.9505 0 1 0 1.0890] readonly
  719. % This TransformPQR implements a relative colorimetric intent by scaling
  720. % the XYZ values relative to the white and black points.
  721.    /TransformPQR
  722.      [ { 5 1 roll                    % p Ws Bs Wd Bd
  723.          4 {3 get 5 1 roll} repeat   % ws bs wd bd p 
  724.          3 index sub                 % ws bs wd bd p-bs 
  725.          1 index                     % ws bs wd bd p-bs bd
  726.          6 2 roll                    % p-bs bd ws bs wd bd 
  727.          sub                         % p-bs bd ws bs wd-bd 
  728.          5 1 roll                    % wd-bd p-bs bd ws bs  
  729.          sub                         % wd-bd p-bs bd ws-bs  
  730.          4 2 roll                    % bd ws-bs wd-bd p-bs 
  731.          mul                         % bd ws-bs (wd-bd)*(p-bs)
  732.          exch div add                % bd + (wd-bd)*(p-bs)/(ws-bs)
  733.        } bind
  734.        { 5 1 roll
  735.          4 {4 get 5 1 roll} repeat
  736.          3 index sub 1 index 6 2 roll sub 5 1 roll
  737.          sub 4 2 roll mul exch div add
  738.        } bind
  739.        { 5 1 roll
  740.          4 {5 get 5 1 roll} repeat
  741.          3 index sub 1 index 6 2 roll sub 5 1 roll
  742.          sub 4 2 roll mul exch div add
  743.        } bind
  744.      ] readonly
  745.    /RangeLMN [0 0.9505 0 1 0 1.0890] readonly
  746.    /MatrixABC
  747.     [ 3.24063 -0.96893  0.05571
  748.      -1.53721  1.87576 -0.20402
  749.      -0.49863  0.04152  1.05700
  750.     ] readonly
  751.    /EncodeABC [ {0 .max 0.45 exp} bind dup dup] readonly
  752.    /WhitePoint [0.9505 1 1.0890] readonly
  753.     % Some Genoa tests seem to require the presence of BlackPoint.
  754.    /BlackPoint [0 0 0] readonly
  755. .dicttomark setcolorrendering
  756.  
  757. %END CRD
  758.  
  759. % Initialize a CIEBased color space for sRGB.
  760. /CIEsRGB [ /CIEBasedABC
  761.   mark
  762.     /DecodeLMN [ {
  763.       dup 0.03928 le { 12.92321 div } { 0.055 add 1.055 div 2.4 exp } ifelse
  764.     } bind dup dup ] readonly
  765.     /MatrixLMN [
  766.       0.412457 0.212673 0.019334
  767.       0.357576 0.715152 0.119192
  768.       0.180437 0.072175 0.950301
  769.     ] readonly
  770.     /WhitePoint [0.9505 1.0 1.0890] readonly
  771.   .dicttomark readonly
  772. ] readonly def
  773.  
  774. % ------ Painting ------ %
  775.  
  776. % A straightforward definition of execform that doesn't actually
  777. % do any caching.
  778. /.execform1 {
  779.     % This is a separate operator so that the stacks will be restored
  780.     % properly if an error occurs.
  781.   dup /Matrix get concat
  782.   dup /BBox get aload pop
  783.   exch 3 index sub exch 2 index sub rectclip
  784.   dup /PaintProc get
  785.   1 index /Implementation known not {
  786.     1 index dup /Implementation null .forceput readonly pop
  787.   } if
  788.   exec
  789. } .bind odef    % must bind .forceput
  790.  
  791. /.formtypes 5 dict
  792.   dup 1 /.execform1 load put
  793. def
  794.  
  795. /execform {            % <form> execform -
  796.   gsave {
  797.     dup /FormType get //.formtypes exch get exec
  798.   } stopped grestore { stop } if
  799. } odef
  800.  
  801. /.patterntypes 5 dict
  802.   dup 1 /.buildpattern1 load put
  803. def
  804.  
  805. /makepattern {            % <proto_dict> <matrix> makepattern <pattern>
  806.   //.patterntypes 2 index /PatternType get get
  807.   .currentglobal false .setglobal exch
  808.         % Stack: proto matrix global buildproc
  809.   3 index dup length 1 add dict .copydict
  810.   3 index 3 -1 roll exec 3 -1 roll .setglobal
  811.   1 index /Implementation 3 -1 roll put
  812.   readonly exch pop exch pop
  813. } odef
  814.  
  815. /setpattern {            % [<comp1> ...] <pattern> setpattern -
  816.   currentcolorspace 0 get /Pattern ne {
  817.     [ /Pattern currentcolorspace ] setcolorspace
  818.   } if setcolor
  819. } odef
  820.  
  821. % Extend image and imagemask to accept dictionaries.
  822. % We must create .imagetypes and .imagemasktypes outside level2dict,
  823. % and leave some extra space because we're still in Level 1 mode.
  824. systemdict begin
  825. /.imagetypes 5 dict
  826.   dup 1 /.image1 load put
  827. def
  828. /.imagemasktypes 5 dict
  829.   dup 1 /.imagemask1 load put
  830. def
  831. end
  832.  
  833. /.image /image load def
  834. /image {
  835.   dup type /dicttype eq {
  836.     dup /ImageType get //.imagetypes exch get exec
  837.   } {
  838.     //.image
  839.   } ifelse
  840. } odef
  841. currentdict /.image undef
  842.  
  843. /.imagemask /imagemask load def
  844. /imagemask {
  845.   dup type /dicttype eq {
  846.     dup /ImageType get //.imagemasktypes exch get exec
  847.   } {
  848.     //.imagemask
  849.   } ifelse
  850. } odef
  851. currentdict /.imagemask undef
  852.  
  853. end                % level2dict
  854.